package eval.experiment;

//import org.apache.log4j.Logger;
import cloud.test.InstalizeTest;

import com.google.inject.Injector;
import eval.deploy.DeploySet;
import eval.deploy.IDemandManager;
import eval.deploy.IDeployGenerator;
import eval.deploy.IDeployManager;
import eval.engine.EmptyPlacement;
import eval.engine.IPlacement;
import eval.engine.IPlacementEngine;
import eval.engine.IplacementEngineFactory;
import eval.engine.FireFighting.FireFightingEngine;
//import eval.engine.cplex.IDataModelGenerator;
import eval.engine.openStack.OpenStackEngine;
import eval.host.Host;
import eval.host.HostGenerator;
import eval.host.IHostManager;
import eval.host.compare.ISortHostList;
import eval.hostEvaluate.IHostEvaluate;
import eval.utilities.configuration.ExperimentConfiguration;
import eval.vm.IVMManager;
import eval.results.IResultManager;
import eval.results.IResultsData;



/**
 * This class represent a single experiment
 * 
 * @author Nicolo' M. Calcavecchia <calcavecchia@elet.polimi.it>
 * */
public class Experiment {

//	static Logger LOG = Logger.getLogger(Experiment.class);

	private static ExperimentConfiguration configuration = ExperimentConfiguration.getSingleton();
	
	private IHostManager hostManager;
	private IDeployManager deployManager;
	private IPlacementEngine placementEngine;
	private IDeployGenerator deployManagerFiller;
	private IResultManager resultManager;

	public Experiment(Injector injector) {
		
		//Injector interface
		this.hostManager = injector.getInstance(IHostManager.class);
		this.deployManager = injector.getInstance(IDeployManager.class);
		this.deployManagerFiller = injector	.getInstance(IDeployGenerator.class);
		this.resultManager = injector.getInstance(IResultManager.class);


		//Generate hosts
		HostGenerator hostGenerator = new HostGenerator(hostManager);
		hostManager.addHosts(hostGenerator.generateHosts(configuration.totalNumberOfHosts));
		hostManager.InitHostsInCloud();
		
		//Generate Demand
		deployManagerFiller.generateDeploys();
		
		//Generate engine
		IplacementEngineFactory placementFactory = injector.getInstance(IplacementEngineFactory.class);
		this.placementEngine = placementFactory.createNewEngine(configuration.optimizationGoal);
		
		
	}

	/**
	 * Runs the experiment over all ticks
	 * */
	public void runExperiment(String resFileName) {
		long experimentStartTime = System.currentTimeMillis();
		IPlacement lastPlacement = new EmptyPlacement();
		IPlacement newPlacement = new EmptyPlacement();

		for (int tick = 0; tick < configuration.experimentTicks ; tick++) {
			/*LOG.info*/System.out.println("\n<-----  TICK ("
					+ tick
//					+ " (ongoing in "
//					+ (10 /*configuration.ongoingOptimizationPeriod*/ - ongoingOptimizationCycle)
					+ ") ----->"
					);
					
//			for(Host host : hostManager.getHosts()){
//				System.out.print(" host: " + host.getHostId() + " load: " +host.getCurrentCpuLoad() + " demand: " + host.getCurrentDemand() + " ");
//			}
//			System.out.print("\n");
			
			long tickStartTime = System.currentTimeMillis();

				newPlacement = placementEngine.computePlacement(tick,lastPlacement);////
	

			resultManager.setExecutionTimesAtTick(tickStartTime,
					placementEngine.getEngineTimeInSec(), tick);
			resultManager.addPlacementAtTick(newPlacement, tick);
			lastPlacement = newPlacement;
			System.gc();
			// end of tick
		}

		resultManager
				.addExperimentTotalTime((System.currentTimeMillis() - experimentStartTime) / 1000.0);
		
		//if needed run saintyCheck at the end of the experiment. 
		if(configuration.enableSaintyCheck){
			resultManager.performSaintyCheck(resFileName);
		}
	}
	
	public IResultsData getResultsData() {
		return resultManager.getResultsData();
	}

}
